package initialize

import (
	"fmt"
	"gin-admin/global"
	"gin-admin/utils"
	"log"
	"os"
	"sync"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type DateWriter struct {
	Mu          sync.Mutex
	BasePath    string
	CurrentDate string
	File        *os.File
}

func NewDateWriter(basePath string) *DateWriter {
	return &DateWriter{
		BasePath:    basePath,
		CurrentDate: time.Now().Format("2006-01-02"),
	}
}

func (dw *DateWriter) Write(p []byte) (n int, err error) {
	dw.Mu.Lock()
	defer dw.Mu.Unlock()
	today := time.Now().Format("2006-01-02")

	if dw.File == nil || today != dw.CurrentDate {
		dw.CurrentDate = today
		if dw.File != nil {
			dw.File.Close()
		}
		file, err := os.OpenFile(dw.BasePath+"-"+today+".log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
		if err != nil {
			return 0, err
		}
		dw.File = file
	}

	return dw.File.Write(p)
}

func (dw *DateWriter) Close() error {
	dw.Mu.Lock()
	defer dw.Mu.Unlock()
	if dw.File != nil {
		return dw.File.Close()
	}
	return nil
}

func InitializeLogger(logLevel zapcore.Level) {
	err := utils.EnsureDirectoryExists(global.GA_CONFIG.Logger.Filepath)
	if err != nil {
		log.Fatalf("创建日志目录失败: %v", err)
	}

	// 设置日志级别
	level := zap.NewAtomicLevelAt(logLevel)

	// 编辑器配置
	encoderConfig := zapcore.EncoderConfig{
		MessageKey:    "message",
		LevelKey:      "level",
		TimeKey:       "time",
		NameKey:       "logger",
		CallerKey:     "caller",
		StacktraceKey: "stacktrace",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeTime: zapcore.TimeEncoder(func(t time.Time, pae zapcore.PrimitiveArrayEncoder) {
			pae.AppendString(t.Format("2006-01-02 15:04:05"))
		}),
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller: zapcore.CallerEncoder(func(ec zapcore.EntryCaller, pae zapcore.PrimitiveArrayEncoder) {
			pae.AppendString(fmt.Sprintf("caller: %v", ec.TrimmedPath()))
		}),
	}

	encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
	consoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	fileEncoder := zapcore.NewJSONEncoder(encoderConfig)

	dateWriter := NewDateWriter(global.GA_CONFIG.Logger.Filepath)

	core := zapcore.NewTee(
		zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), level),
		zapcore.NewCore(fileEncoder, zapcore.AddSync(dateWriter), level),
	)
	logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
	global.GA_LOGGER = logger
}
